package com.sz.biz.logistics.core.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.base.entity.RegionSchema;
import com.sz.biz.logistics.core.entity.ServiceRegionRel;
import com.sz.biz.logistics.base.service.RegionSchemaService;
import com.sz.biz.logistics.core.service.ServiceRegionRelService;
import com.sz.biz.logistics.core.dto.ServiceRegionCustomerDto;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.service.SysUserSupport;
import com.sz.common.core.system.service.UserModel;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Function:  ServiceCargoTypeRelService <br>
 * Author: penghui.zheng <br>
 * Date: 2017-05-9 14:58:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ServiceRegionRelServiceImpl extends AbstractService implements ServiceRegionRelService {

    @Autowired
    private RegionSchemaService regionSchemaService;

    @Autowired
    private SysUserSupport userSupport;

    /**
     * 新增
     *
     * @param entry 新增的实体
     * @return 新增是否成功
     */
    @Override
    public String save(ServiceRegionRel entry) {
        //判断服务范围类型是否重复
        ServiceRegionRel serviceRegionRel = checkServiceRegionExist(entry.getServiceId(), entry.getType());
        if (null != serviceRegionRel) {
            throw Exceptions.bizException(ErrorCodes.ERROR_SERVICE_REGION_TYPE_EXIST, "");
        }
        //生成15位的服务范围编码
        entry.setCode(generateServiceReginCode());
        //判断分区编码是否重复
        checkCode(entry.getCode());
        //保存范围分区
        String uid = saveRegionSchema(entry);
        entry.setCreateUserId(PrincipalUtils.getAccountId());
        entry.setSchemaUid(uid);
        dao.save(getSqlName("insert"), entry);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_SERVICE_REGION", entry);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ,
                ModuleNames.BIZ_SERVICE_REGION,
                UserActions.ADD,
                "添加服务服务范围",
                dataBackup);

        return entry.getSchemaUid();
    }

    /**
     * 生成15位的服务范围编码
     *
     * @return
     */
    private String generateServiceReginCode() {
        String code = RandomStringUtils.randomAlphabetic(15);
        //判断服务范围编码是否重复
        RegionSchema regionSchema = regionSchemaService.findByCodeAndType(code, 3);
        if (null != regionSchema) {
            generateServiceReginCode();
        }
        return code;
    }

    private String saveRegionSchema(ServiceRegionRel entry) {
        //创建分区方案
        Date now = dao.getDbDate();
        RegionSchema regionSchema = new RegionSchema();
        regionSchema.setName(entry.getType() + "_" + entry.getCode());
        regionSchema.setCode(entry.getCode());
        regionSchema.setType(3);    //服务范围分区
        regionSchema.setDescription(entry.getRemark());
        regionSchema.setUid(generateNewUid());
        regionSchema.setActiveTime(now);
        regionSchema.setCreateTime(now);
        regionSchema.setIsActive(true);
        regionSchema.setCreateUserId(PrincipalUtils.getAccountId());
        regionSchema.setLastUpdateUserId(PrincipalUtils.getAccountId());
        String uid = regionSchemaService.save(regionSchema);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_SERVICE_REGION_SCHEMA", regionSchema);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ,
                ModuleNames.BIZ_SERVICE_REGION_SCHEMA,
                UserActions.ADD,
                "添加服务服务范围的分区方案",
                dataBackup);
        return uid;
    }

    /**
     * 异步判断服务范围编码是否存在
     *
     * @param id
     * @param code
     */
    @Override
    public void checkServiceRegionCode(Integer id, String code) {
        if (null != id) {
            //获取服务范围信息
            ServiceRegionRel serviceRegionRel = findById(id);
            //修改为新的code时验证code是否唯一
            if (null == serviceRegionRel || !code.equals(serviceRegionRel.getCode())) {
                checkCode(code);
            }
        } else {
            checkCode(code);
        }
    }

    /**
     * 验证编码是否重复
     *
     * @param code
     */
    private void checkCode(String code) {
        RegionSchema regionSchema = regionSchemaService.findByCodeAndType(code, 3);
        if (null != regionSchema) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, "");
        }
    }

    /**
     * 修改服务范围
     *
     * @param entry
     * @return
     */
    @Override
    public String update(ServiceRegionRel entry) {
        //获取老数据
        ServiceRegionRel serviceRegionRelExist = findById(entry.getId());
        //如果旧的数据存在并且类型和新的数据不一致就判断类型是否存在
        if (null != serviceRegionRelExist && !serviceRegionRelExist.getType().equals(entry.getType())) {
            //判断服务范围类型是否重复
            ServiceRegionRel serviceRegionRel = checkServiceRegionExist(entry.getServiceId(), entry.getType());
            if (null != serviceRegionRel) {
                throw Exceptions.bizException(ErrorCodes.ERROR_SERVICE_REGION_TYPE_EXIST, "");
            }
        }
        //如果旧数据的编码和新的编码不一致就判断编码是否重复
        if (null != serviceRegionRelExist && null != entry.getCode() && !entry.getCode().equals(serviceRegionRelExist.getCode())) {
            //判断分区编码是否重复
            checkCode(entry.getCode());
            //删除分区方案
            List<RegionSchema> regionSchemaList = new ArrayList<>();
            RegionSchema regionSchema = new RegionSchema();
            regionSchema.setUid(entry.getSchemaUid());
            regionSchema.setIsDeleted(true);
            regionSchema.setType(3);
            regionSchemaList.add(regionSchema);
            regionSchemaService.batchDeleteByUids(regionSchemaList);
            //创建分区方案
            String uid = saveRegionSchema(entry);
            entry.setSchemaUid(uid);
        }
        dao.update(getSqlName("update"), entry);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_SERVICE_REGION", entry);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ,
                ModuleNames.BIZ_SERVICE_REGION,
                UserActions.UPDATE,
                "修改服务服务范围",
                dataBackup);
        return serviceRegionRelExist.getSchemaUid();
    }

    /**
     * 根据id删除
     *
     * @param ids
     */
    @Override
    public void batchDeleteById(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        List<RegionSchema> regionSchemaList = new ArrayList<>();
        for (Integer id : ids) {
            ServiceRegionRel serviceRegionRel = findById(id);
            if (null != serviceRegionRel) {
                //删除分区方案
                RegionSchema regionSchema = new RegionSchema();
                regionSchema.setUid(serviceRegionRel.getSchemaUid());
                regionSchema.setIsDeleted(true);
                regionSchema.setType(3);
                regionSchemaList.add(regionSchema);
            }
        }
        regionSchemaService.batchDeleteByUids(regionSchemaList);
        //删除服务范围信息
        Map<String, Object> map = new HashMap<>();
        map.put("ids", ids);
        dao.delete(getSqlName("batchDeleteById"), map);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_SERVICE_REGION", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ,
                ModuleNames.BIZ_SERVICE_REGION,
                UserActions.DELETE, "根据id删除服务服务范围", dataBackup);

    }

    /**
     * 判断服务范围类型是否重复： 唯一的起点和终点
     *
     * @param serviceId serviceId
     * @param type type
     * @return
     */
    private ServiceRegionRel checkServiceRegionExist(Integer serviceId, String type) {
        ParamData paramData = new ParamData();
        paramData.put("serviceId", serviceId);
        paramData.put("type", type);
        return (ServiceRegionRel) dao.findForObject(getSqlName("findByServiceIdAndType"), paramData);
    }

    /**
     * 根据serviceId查询单个实体
     *
     * @param serviceId serviceId
     * @return 查询出来的实体对象
     */
    @Override
    public List<ServiceRegionRel> findByServiceId(int serviceId) {
        //获取所有的服务id
        List<ServiceRegionRel> rels = dao.findForList(getSqlName("findByServiceId"), serviceId, ServiceRegionRel.class);
        rels.stream().filter(rel -> userSupport != null && rel.getCreateUserId() != null).forEach(rel -> {
            UserModel user = userSupport.getUserById(rel.getCreateUserId());
            if (user != null) {
                rel.setCreator(user.getFullName() + " " + user.getAccountName());
            }
        });
        return rels;
    }

    /**
     * 服务范围
     *
     * @param serviceId serviceId
     * @return List
     */
    @Override
    public List<ServiceRegionCustomerDto> findRegionInfoByServiceId(int serviceId) {
        return dao.findForList(getSqlName("findRegionInfoByServiceId"), serviceId, ServiceRegionCustomerDto.class);
    }

    /**
     * 批量新增
     *
     * @param list
     */
    @Override
    public void batchsave(List<ServiceRegionRel> list) {
        dao.batchInsert(getSqlName("insert"), list);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_SERVICE_REGION", list);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ,
                ModuleNames.BIZ_SERVICE_REGION,
                UserActions.ADD,
                "添加服务服务范围",
                dataBackup);
    }

    /**
     * 根据主键Id查询单个实体
     *
     * @param id 主键id
     * @return 查询出来的实体对象
     */
    @Override
    public ServiceRegionRel findById(Integer id) {
        return (ServiceRegionRel) dao.findForObject(getSqlName("findById"), id);
    }

    /**
     * 根据serviceId删除
     *
     * @param serviceId serviceId
     */
    @Override
    public void deleteByServiceId(Integer serviceId) {
        dao.delete(getSqlName("deleteByServiceId"), serviceId);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_SERVICE_REGION", serviceId);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ,
                ModuleNames.BIZ_SERVICE_REGION,
                UserActions.DELETE, "删除服务服务范围", dataBackup);
    }

    @Override
    protected String getMapperNamespace() {
        return "ServiceRegionRelMapper";
    }
}
